/** @file @file

Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2011, Apple Inc. All rights reserved.
Copyright (c) 2006 - 2023, Kunlun BIOS, Kunlun Technology (Beijing) Co., Ltd.. All
Rights Reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include "PlatformBm.h"
//[gliu-0020]
#include <Protocol/SerialIo.h>
//#include <TerminalDxe.h>
//[gliu-0020]
//#include <Protocol/CrPolicyProtocol.h>
//[jckuang-0020]
#include <Library/PostCodeLib.h>
#include <Library/ReportStatusCodeLib.h>
#include "PostCode.h"
#include <Protocol/DevicePathToText.h>
//[jckuang-0020]
//[gliu-0009]
#if FixedPcdGetBool(PcdX100PortControl)
SYSTEM_SETUP_CONFIGURATION       *mSetupConfiguration;
//EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *mDevPathToText = NULL;
//CHAR16                           mUsbMsTable[TOTAL_USB_MS_NUMBER][PATH_TEXT_LENGTH];
//CHAR16                           mUsbKbTable[TOTAL_USB_MS_NUMBER][PATH_TEXT_LENGTH];
//UINTN                            mUsbKbNumber = 0;
//UINTN                            mUsbMsNumber = 0;
#endif
//[gliu-0009]

EFI_GUID mBootMenuFile = {
  0xEEC25BDC, 0x67F2, 0x4D95, { 0xB1, 0xD5, 0xF8, 0x1B, 0x20, 0x39, 0xD1, 0x1D }
};


extern BOOLEAN  gFbFlag;
//add-klk-lyang-P000A-start//
VOID
PlatformBdsRegisterStaticBootOptions (
  VOID
  );
//add-klk-lyang-P000A-end//

//
//
// Toggle state
//
// TOGGLE_STATE_VALID    0x80
// SCROLL_LOCK_ACTIVE    0x01
// NUM_LOCK_ACTIVE       0x02
// CAPS_LOCK_ACTIVE      0x04
//


/**
  Brief description of FvFilePath.

  @param  FileGuid

**/
EFI_DEVICE_PATH *
FvFilePath (
  EFI_GUID                     *FileGuid
  )
{

  EFI_STATUS                         Status;
  EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;
  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  FileNode;

  EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);

  Status = gBS->HandleProtocol (
                  gImageHandle,
                  &gEfiLoadedImageProtocolGuid,
                  (VOID **) &LoadedImage
                  );
  ASSERT_EFI_ERROR (Status);
  return AppendDevicePathNode (
           DevicePathFromHandle (LoadedImage->DeviceHandle),
           (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
           );
}

/**
  Create one boot option for BootManagerMenuApp.

  @param  FileGuid          Input file guid for the BootManagerMenuApp.
  @param  Description       Description of the BootManagerMenuApp boot option.
  @param  Position          Position of the new load option to put in the ****Order variable.
  @param  IsBootCategory    Whether this is a boot category.


  @retval OptionNumber      Return the option number info.

**/
UINTN
RegisterBootManagerMenuAppBootOption (
  EFI_GUID                         *FileGuid,
  CHAR16                           *Description,
  UINTN                            Position,
  BOOLEAN                          IsBootCategory
  )
{
  EFI_STATUS                       Status;
  EFI_BOOT_MANAGER_LOAD_OPTION     NewOption;
  EFI_DEVICE_PATH_PROTOCOL         *DevicePath;
  UINTN                            OptionNumber;

  DevicePath = FvFilePath (FileGuid);
  Status = EfiBootManagerInitializeLoadOption (
             &NewOption,
             LoadOptionNumberUnassigned,
             LoadOptionTypeBoot,
             IsBootCategory ? LOAD_OPTION_ACTIVE : LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_HIDDEN,//ADD BY LYANG
             Description,
             DevicePath,
             NULL,
             0
             );
  ASSERT_EFI_ERROR (Status);
  FreePool (DevicePath);

  Status = EfiBootManagerAddLoadOptionVariable (&NewOption, Position);
  ASSERT_EFI_ERROR (Status);

  OptionNumber = NewOption.OptionNumber;

  EfiBootManagerFreeLoadOption (&NewOption);

  return OptionNumber;
}

/**
  Check if it's a Device Path pointing to BootManagerMenuApp.

  @param  DevicePath     Input device path.

  @retval TRUE   The device path is BootManagerMenuApp File Device Path.
  @retval FALSE  The device path is NOT BootManagerMenuApp File Device Path.
**/
BOOLEAN
IsBootManagerMenuAppFilePath (
  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
)
{
  EFI_HANDLE                      FvHandle;
  VOID                            *NameGuid;
  EFI_STATUS                      Status;

  Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePath, &FvHandle);
  if (!EFI_ERROR (Status)) {
    NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath);
    if (NameGuid != NULL) {
      return CompareGuid (NameGuid, &mBootMenuFile);
    }
  }

  return FALSE;
}

/**
  Return the boot option number to the BootManagerMenuApp.

  If not found it in the current boot option, create a new one.

  @retval OptionNumber   Return the boot option number to the BootManagerMenuApp.

**/
UINTN
GetBootManagerMenuAppOption (
  VOID
  )
{
  UINTN                        BootOptionCount;
  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
  UINTN                        Index;
  UINTN                        OptionNumber;

  OptionNumber = 0;

  BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);

  for (Index = 0; Index < BootOptionCount; Index++) {
    if (IsBootManagerMenuAppFilePath (BootOptions[Index].FilePath)) {
      OptionNumber = BootOptions[Index].OptionNumber;
      break;
    }
  }

  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);

  if (Index >= BootOptionCount) {
//add-klk-lyang-P000A-start//
    gFbFlag = TRUE;
//add-klk-lyang-P000A-end//
    //
    // If not found the BootManagerMenuApp, create it.
    //
    OptionNumber = (UINT16) RegisterBootManagerMenuAppBootOption (&mBootMenuFile, L"UEFI BootManagerMenuApp", (UINTN) -1, FALSE);
  }

  return OptionNumber;
}
//start-klk-alt-P000A-add//
/**
  Connect RootBridge

  @retval EFI_SUCCESS   Connect RootBridge successfully.
  @retval EFI_STATUS    Connect RootBridge fail.

**/
EFI_STATUS
ConnectRootBridge (
  VOID
  )
{
  EFI_STATUS                Status;
  EFI_HANDLE                RootHandle;
  UINT8                     BrdgeCount;

  BrdgeCount = 0;
  //[jckuang-0020]
  REPORT_STATUS_CODE(EFI_PROGRESS_CODE, BDS_PCI_BUS_BEGIN);//[gliu-0062]
  //[jckuang-0020]
  while(gPlatformRootBridges[BrdgeCount] != NULL){
    //
    // Make all the PCI_IO protocols on PCI Seg 0 show up
    //
    Status = EfiBootManagerConnectDevicePath (gPlatformRootBridges[BrdgeCount], NULL);
    Status = gBS->LocateDevicePath (
                    &gEfiDevicePathProtocolGuid,
                    &gPlatformRootBridges[BrdgeCount],
                    &RootHandle
                    );
    DEBUG ((EFI_D_INFO, "Pci Root bridge handle is 0x%X\n", RootHandle));

    if (EFI_ERROR (Status)) {
      return Status;
    }
    //
    // PostCode = 0x15, PCI enumeration complete
    //
 
    Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    BrdgeCount++;
  }
  //[jckuang-0020]
  REPORT_STATUS_CODE(EFI_PROGRESS_CODE, BDS_PCI_ENUMERATION_END);
  //[jckuang-0020]
  return EFI_SUCCESS;
}

/**
  Brief description of GetAllVgaHandles.

  @param  VgaHandleBuffer
  @param  VgaHandleCount

  @retval EFI_SUCCESS   Function successful returned.
**/
EFI_STATUS
GetAllVgaHandles (
  OUT EFI_HANDLE  **VgaHandleBuffer,
  OUT UINTN       *VgaHandleCount
  )
{
  EFI_STATUS                            Status;
  EFI_HANDLE                            *HandleBuffer;
  UINTN                                 HandleCount;
  UINTN                                 HandleIndex;
  EFI_PCI_IO_PROTOCOL                   *PciIo;
  PCI_TYPE00                            Pci;
  EFI_HANDLE                            *TempVgaHandleBuffer;
  UINTN                                 BufferIndex;

  HandleBuffer        = NULL;
  HandleCount         = 0;
  BufferIndex         = 0;

  //
  // check all the pci io to find all possible VGA devices
  //
  Status = gBS->LocateHandleBuffer (
                  ByProtocol,
                  &gEfiPciIoProtocolGuid,
                  NULL,
                  &HandleCount,
                  &HandleBuffer
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = gBS->AllocatePool (
                  EfiBootServicesData,
                  (HandleCount * sizeof(EFI_HANDLE)),
                  (VOID **) &TempVgaHandleBuffer
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
    Status = gBS->HandleProtocol (HandleBuffer[HandleIndex], &gEfiPciIoProtocolGuid, (VOID **)&PciIo);
    if (!EFI_ERROR (Status)) {
      //
      // Check for all VGA device
      //
      Status = PciIo->Pci.Read (
                            PciIo,
                            EfiPciIoWidthUint32,
                            0,
                            sizeof (Pci) / sizeof (UINT32),
                            &Pci
                            );
      if (EFI_ERROR (Status)) {
        continue;
      }

//modify-klk-lyang-P000A-start//
      if (!IS_PCI_DISPLAY (&Pci)) {
//modify-klk-lyang-P000A-end//
        continue;
      }

      TempVgaHandleBuffer[BufferIndex] = HandleBuffer[HandleIndex];
      BufferIndex++;
    }
  }

  if (BufferIndex == 0) {

    return EFI_NOT_FOUND;
  }

  Status = gBS->AllocatePool (
                  EfiBootServicesData,
                  (BufferIndex * sizeof(EFI_HANDLE)),
                  (VOID **) VgaHandleBuffer
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  gBS->CopyMem (*VgaHandleBuffer, TempVgaHandleBuffer, (BufferIndex * sizeof(EFI_HANDLE)));

  *VgaHandleCount = BufferIndex;

  gBS->FreePool (HandleBuffer);
  gBS->FreePool (TempVgaHandleBuffer);

  return EFI_SUCCESS;
}

/**
  Brief description of SelectVgaHandle.

  @param  VgaDeviceList
  @param  VgaHandleCount

**/
EFI_HANDLE
SelectVgaHandle (
  IN VGA_DEVICE_INFO                    *VgaDeviceList,
  IN UINTN                              VgaHandleCount
  )
{
  UINT8                                 CheckSequenceIndex;
  UINT8                                 SelectedVgaIndex;
  UINT8                                 ListIndex;
  POSSIBLE_VGA_TYPE                     CheckSequence[] = {OnBoard,PlugIn};

  SelectedVgaIndex = 0xFF;

  CheckSequence[0] = PlugIn;
  CheckSequence[1] = OnBoard;

  for (CheckSequenceIndex = 0; CheckSequenceIndex < PossibleVgaTypeMax; CheckSequenceIndex++) {
    for (ListIndex = 0; ListIndex < VgaHandleCount; ListIndex++) {
      if ((VgaDeviceList[ListIndex].VgaType == CheckSequence[CheckSequenceIndex]) &&
          ((SelectedVgaIndex == 0xFF) ||
           ((SelectedVgaIndex != 0xFF) &&
            (VgaDeviceList[ListIndex].Priority < VgaDeviceList[SelectedVgaIndex].Priority)))) {
        SelectedVgaIndex = ListIndex;
      }
    }
    if (SelectedVgaIndex != 0xFF) {
      return VgaDeviceList[SelectedVgaIndex].Handle;
    }
  }

  return NULL;
}

/**
  Brief description of ClassifyVgaHandleAndSelect.

  @param  PciVgaHandleBuffer
  @param  PciVgaHandleCount

**/
EFI_HANDLE
ClassifyVgaHandleAndSelect (
  IN EFI_HANDLE                         *PciVgaHandleBuffer,
  IN UINTN                              PciVgaHandleCount
  )
{
  EFI_STATUS                            Status;
  UINTN                                 VgaHandleCount;
  VGA_DEVICE_INFO                       *VgaDeviceList;
  EFI_HANDLE                            SelectedVgaHandle;
  UINTN                                 Index;
  EFI_DEVICE_PATH_PROTOCOL              *DevicePath;
  BOOLEAN                               FoundFlag;
  UINT8                                 ListIndex;
  UINT8                                 CompareIndex;
  POSSIBLE_VGA_TYPE                     CompareVgaTypeArray[] = {OnBoard, PlugIn};
  EFI_DEVICE_PATH_PROTOCOL              **CompareDeviceArray[] = {
    (EFI_DEVICE_PATH_PROTOCOL**)gPlatformAllPossibleOnBoardConsole, // Must put in the first
    (EFI_DEVICE_PATH_PROTOCOL**)gPlatformAllPossiblePcieConsole
  };

  SelectedVgaHandle = NULL;
  VgaHandleCount = PciVgaHandleCount;
  if (VgaHandleCount == 0) {
    return NULL;
  }

  if (VgaHandleCount == 1) {
    return PciVgaHandleBuffer[0];
  }else{
    return PciVgaHandleBuffer[1];
  }
  Status = gBS->AllocatePool (
                  EfiBootServicesData,
                  (VgaHandleCount * sizeof(VGA_DEVICE_INFO)),
                  (VOID **) &VgaDeviceList
                  );
  if (EFI_ERROR (Status)) {
    return NULL;
  }

  for (Index = 0; Index < VgaHandleCount; Index++) {
    Status = gBS->HandleProtocol (
                    PciVgaHandleBuffer[Index],
                    &gEfiDevicePathProtocolGuid,
                    (VOID **)&DevicePath
                    );
    VgaDeviceList[Index].Handle = PciVgaHandleBuffer[Index];
    FoundFlag = FALSE;
    for (CompareIndex = 0; CompareIndex < PossibleVgaTypeMax; CompareIndex ++) {
      ListIndex = 0;
      while ((CompareDeviceArray[CompareIndex])[ListIndex] != NULL) {
        if (CompareMem (
              DevicePath,
              (CompareDeviceArray[CompareIndex])[ListIndex],
              GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH
              ) == 0) {
          VgaDeviceList[Index].VgaType = CompareVgaTypeArray[CompareIndex];
          VgaDeviceList[Index].Priority = ListIndex;
          FoundFlag = TRUE;
          break;
        }
        ListIndex++;
      }
    }
    if (FoundFlag) {
      continue;
    }

    //
    // VGA Information Default Setting
    //
    VgaDeviceList[Index].VgaType = PlugIn;
    VgaDeviceList[Index].Priority = 100;
  }
  SelectedVgaHandle = SelectVgaHandle (VgaDeviceList, VgaHandleCount);

  gBS->FreePool (VgaDeviceList);
  return SelectedVgaHandle;
}

/**
  Brief description of GetGopDevicePath.

  @param  PciDevicePath
  @param  GopDevicePath

  @retval EFI_SUCCESS   Function successful returned.
**/
EFI_STATUS
GetGopDevicePath (
   IN  EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
   OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
   )
{
  UINTN                           Index;
  EFI_STATUS                      Status;
  EFI_HANDLE                      PciDeviceHandle;
  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
  EFI_DEVICE_PATH_PROTOCOL        *TempPciDevicePath;
  UINTN                           GopHandleCount;
  EFI_HANDLE                      *GopHandleBuffer;

  if (PciDevicePath == NULL || GopDevicePath == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Initialize the GopDevicePath to be PciDevicePath
  //
  *GopDevicePath    = PciDevicePath;
  TempPciDevicePath = PciDevicePath;

  Status = gBS->LocateDevicePath (
                  &gEfiDevicePathProtocolGuid,
                  &TempPciDevicePath,
                  &PciDeviceHandle
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Try to connect this handle, so that GOP dirver could start on this
  // device and create child handles with GraphicsOutput Protocol installed
  // on them, then we get device paths of these child handles and select
  // them as possible console device.
  //
  Status = gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
  if (EFI_ERROR(Status)) {
    //
    // reserve for connect fail.
    //

  }
  Status = gBS->LocateHandleBuffer (
                  ByProtocol,
                  &gEfiGraphicsOutputProtocolGuid,
                  NULL,
                  &GopHandleCount,
                  &GopHandleBuffer
                  );
  if (!EFI_ERROR (Status)) {
    //
    // Add all the child handles as possible Console Device
    //
    for (Index = 0; Index < GopHandleCount; Index++) {
      Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
      if (EFI_ERROR (Status)) {
        continue;
      }
      if (CompareMem (
            PciDevicePath,
            TempDevicePath,
            GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
            ) == 0) {
        //
        // In current implementation, we only enable one of the child handles
        // as console device, i.e. sotre one of the child handle's device
        // path to variable "ConOut"
        // In futhure, we could select all child handles to be console device
        //

        *GopDevicePath = TempDevicePath;

        //
        // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
        // Add the integrity GOP device path.
        //
        EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);
        EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);
//remove-klk-lyang-P000A-start//
        //EfiBootManagerUpdateConsoleVariable (ConOut, NULL, PciDevicePath);
//remove-klk-lyang-P000A-end//
        EfiBootManagerUpdateConsoleVariable (ConOut, TempDevicePath, NULL);
      }
    }
    gBS->FreePool (GopHandleBuffer);
  }

  return EFI_SUCCESS;
}

/**
  Add PCI VGA to ConOut.
  PCI VGA: 03 00 00

  @param  DeviceHandle    Handle of PCIIO protocol.
  @param  GopDevicePath

  @retval EFI_SUCCESS     PCI VGA is added to ConOut.
  @retval EFI_STATUS      No PCI VGA device is added.

**/
EFI_STATUS
PreparePciVgaDevicePath (
  IN EFI_HANDLE                DeviceHandle,
  IN EFI_DEVICE_PATH_PROTOCOL  **GopDevicePath
  )
{
  EFI_STATUS                Status;
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;

  DevicePath = NULL;
  Status = gBS->HandleProtocol (
                  DeviceHandle,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **)&DevicePath
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  GetGopDevicePath (DevicePath, GopDevicePath);

  return EFI_SUCCESS;
}

/**
  Find the platform active vga, and base on the policy to enable the vga as the console out device.
  The policy is driven by one setup variable "VBIOS".

  @retval EFI_UNSUPPORTED   There is no active vga device
  @retval EFI_STATUS        Return the status of BdsLibGetVariableAndSize ()

**/
EFI_STATUS
PlatformBdsForceActiveVga (
  VOID
  )
{
  EFI_STATUS                            Status;
  EFI_HANDLE                            *VgaHandleBuffer;
  UINTN                                 VgaHandleCount;
  EFI_HANDLE                            *SelectedVgaHandle;
  EFI_DEVICE_PATH_PROTOCOL              *ConOutDevPath;
//add-klk-lyang-P000A-start//
  UINT8                                 Index;
//add-klk-lyang-P000A-end//
  VgaHandleBuffer     = NULL;
  VgaHandleCount      = 0;

  Status = GetAllVgaHandles (&VgaHandleBuffer, &VgaHandleCount);
  if (EFI_ERROR (Status)) {
    goto Exit;
  }
//add-klk-lyang-P000A-start//
  for (Index = 0; Index < VgaHandleCount; Index++) {
    PreparePciVgaDevicePath (VgaHandleBuffer[Index], &ConOutDevPath);
  }
  goto  Exit;
//add-klk-lyang-P000A-end//
  //
  //Select and connect VGA handle.
  //
  SelectedVgaHandle = ClassifyVgaHandleAndSelect (
                        VgaHandleBuffer,
                        VgaHandleCount
                        );
  //
  //Update conout variable.
  //
  PreparePciVgaDevicePath (SelectedVgaHandle, &ConOutDevPath);

Exit:
  if (VgaHandleBuffer) {
    gBS->FreePool (VgaHandleBuffer);
  }

  return Status;
}

/**
  Check if it's a Device Path pointing to BootManagerMenuApp.

  @param  DevicePath     Input device path.
  @param  FileGuid

  @retval TRUE   The device path is BootManagerMenuApp File Device Path.
  @retval FALSE  The device path is NOT BootManagerMenuApp File Device Path.
**/
BOOLEAN
IsMenuAppFilePath (
  EFI_DEVICE_PATH_PROTOCOL     *DevicePath,
  VOID                         *FileGuid
)
{
  EFI_HANDLE                      FvHandle;
  VOID                            *NameGuid;
  EFI_STATUS                      Status;
  VOID                            *BootManagerFile;

  BootManagerFile = FileGuid;
  Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePath, &FvHandle);
  if (!EFI_ERROR (Status)) {
    NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath);
    if (NameGuid != NULL) {
      return CompareGuid (NameGuid, BootManagerFile);
    }
  }

  return FALSE;
}


/**
  Return the boot option number to the BootManagerMenuApp.

  If not found it in the current boot option, create a new one.

  @param  BootManagerFile
  @param  Description

  @retval OptionNumber   Return the boot option number to the BootManagerMenuApp.

**/
UINTN
GetHotkeyAppOption (
  VOID          *BootManagerFile,
  CHAR16        *Description
  )
{
  UINTN                        BootOptionCount;
  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
  UINTN                        Index;
  UINTN                        OptionNumber;

  OptionNumber = 0;

  BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);

  for (Index = 0; Index < BootOptionCount; Index++) {
    if (IsMenuAppFilePath (BootOptions[Index].FilePath,BootManagerFile)) {
      OptionNumber = BootOptions[Index].OptionNumber;
      break;
    }
  }

  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);

  if (Index >= BootOptionCount) {
    //
    // If not found the BootManagerMenuApp, create it.
    //
    OptionNumber = (UINT16) RegisterBootManagerMenuAppBootOption (BootManagerFile, Description, (UINTN) -1, FALSE);
  }

  return OptionNumber;
}



VOID
EFIAPI
PlatformBootManagerBeforeConsole (
  VOID
  )
{
  UINTN                             Index;
//add-klk-lyang-P000A-start//
  EFI_STATUS                        Status;
  SYSTEM_SETUP_CONFIGURATION        *SetupVar;
  ESRT_MANAGEMENT_PROTOCOL          *EsrtManagement;

//add-klk-lyang-P000A-end//
//remove-klk-lyang-P000A-start//
  //SetupVariableInit ();
//remove-klk-lyang-P000A-end//
//add-klk-lyang-P000A-start//
  if (GetBootModeHob() != BOOT_ON_FLASH_UPDATE) {
    EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
  }
//add-klk-lyang-P000A-end//
//add-klk-lyang-P000A-start//
  //
  // Start PciBus.
  //
  ConnectRootBridge ();

  SetupVar = NULL;
  Status = KlSetupVarRead(&SetupVar);
  if(!EFI_ERROR(Status)){

//[gliu-0009]
#if FixedPcdGetBool(PcdX100PortControl)
    DEBUG((DEBUG_ERROR, "PlatformBootManagerBeforeConsole:Init X100 Config!\n"));
    X100ConfigParaInit(SetupVar);
    /*Status = gBS->LocateProtocol(
        &gEfiDevicePathToTextProtocolGuid,
        NULL,
        (VOID**)&mDevPathToText);*/
    //ASSERT_EFI_ERROR(Status);
    ControlX100DevEnable (SetupVar);
    ModifyPciRootPortTag (SetupVar);
#endif
//[gliu-0009]
    if(SetupVar != NULL){
      FreePool(SetupVar);
    }

  }
//add-klk-lyang-P000A-end//
  Index   = 0;
  while (gPlatformConsole[Index].DevicePath != NULL) {
    //
    // Update the console variable with the connect type
    //
    if ((gPlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
      EfiBootManagerUpdateConsoleVariable (ConIn, gPlatformConsole[Index].DevicePath, NULL);

    }

    if ((gPlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
      EfiBootManagerUpdateConsoleVariable (ConOut, gPlatformConsole[Index].DevicePath, NULL);

    }

    if ((gPlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
      EfiBootManagerUpdateConsoleVariable (ErrOut, gPlatformConsole[Index].DevicePath, NULL);

    }

    Index++;
  }

  PlatformBdsForceActiveVga ();
//add-klk-lyang-P000A-start//
  PlatformBdsRegisterStaticBootOptions ();
  //
  //Capsules
  //
  Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
  if (EFI_ERROR(Status)) {
    EsrtManagement = NULL;
  }
  switch (GetBootModeHob()) {
  case BOOT_ON_FLASH_UPDATE:
    //
    // Fix up Frontpage not display update info
    //
    EfiBootManagerConnectAll ();
    DEBUG((DEBUG_INFO, "ProcessCapsules Before EndOfDxe ......\n"));
    Status = ProcessCapsules ();
    DEBUG((DEBUG_INFO, "ProcessCapsules %r\n", Status));
//add-klk-lyang-P000A-start//maybe unreachable
    EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
//add-klk-lyang-P000A-end//
    break;
  case BOOT_IN_RECOVERY_MODE:
    break;
  case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
  case BOOT_WITH_MINIMAL_CONFIGURATION:
  case BOOT_ON_S4_RESUME:
    if (EsrtManagement != NULL) {
      //
      // Lock ESRT cache repository before EndofDxe if ESRT sync is not needed
      //
      EsrtManagement->LockEsrtRepository();
    }
    break;
  default:
    //
    // Require to sync ESRT from FMP in a new boot
    //
    if (EsrtManagement != NULL) {
      EsrtManagement->SyncEsrtFmp();
    }
    break;
  }

//add-klk-lyang-P000A-end//
}

CHAR16 *
DevicePathToStr (
  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
  )
{
 // EFI_STATUS                       Status;
  CHAR16                           *ToText;
  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;

  if (DevPath == NULL) {
    return NULL;
  }

   gBS->LocateProtocol (
                  &gEfiDevicePathToTextProtocolGuid,
                  NULL,
                  (VOID **) &DevPathToText
                  );
 // ASSERT_EFI_ERROR (Status);
  ToText = DevPathToText->ConvertDevicePathToText (
                            DevPath,
                            FALSE,
                            TRUE
                            );
 // ASSERT (ToText != NULL);
  return ToText;
}





/**
   Install gKunLunAllDriversConnectedProtocolGuid for callback function.
**/
VOID
InstallAlldriversConnected()
{
  EFI_STATUS  Status;
  EFI_HANDLE  Handle = NULL;

  //KeyBoardStateControl();//[gliu-0051]
  Status = gBS->InstallProtocolInterface (&Handle, &gKunLunAllDriversConnectedProtocolGuid, EFI_NATIVE_INTERFACE,NULL);
  if(!EFI_ERROR(Status)){
    Status = gBS->UninstallProtocolInterface (Handle, &gKunLunAllDriversConnectedProtocolGuid, NULL);
  }
}

/**
  Connect with predefined platform connect sequence,
  the OEM/IBV can customize with their own connect sequence.
**/
VOID
PlatformBdsConnectSequence (
  VOID
  )
{
  EfiBootManagerConnectAll ();
  //
  // Just use the simple policy to connect all devices
  //
  //EfiBootManagerConnectAll ();
  InstallAlldriversConnected();
}

/**
  Perform the platform diagnostic, such like test memory. OEM/IBV also
  can customize this fuction to support specific platform diagnostic.

  @param MemoryTestLevel The memory test intensive level
  @param QuietBoot       Indicate if need to enable the quiet boot
**/
VOID
PlatformBdsDiagnostics (
  IN EXTENDMEM_COVERAGE_LEVEL    MemoryTestLevel,
  IN BOOLEAN                     QuietBoot
  )
{
  EFI_STATUS  Status;

  //
  // Here we can decide if we need to show
  // the diagnostics screen
  //
  if (QuietBoot) {
    BootLogoEnableLogo ();

    //
    // Perform system diagnostic
    //
    Status = PlatformBootManagerMemoryTest (MemoryTestLevel);
    if (EFI_ERROR (Status)) {
      BootLogoDisableLogo ();
    }

    return;
  }

  //
  // Perform system diagnostic
  //
  PlatformBootManagerMemoryTest (MemoryTestLevel);
}

/**
  Register the static boot options.
**/
VOID
PlatformBdsRegisterStaticBootOptions (
  VOID
  )
{
  //EFI_GRAPHICS_OUTPUT_BLT_PIXEL  Black;
  //EFI_GRAPHICS_OUTPUT_BLT_PIXEL  White;
  EFI_INPUT_KEY                  Enter;
  EFI_INPUT_KEY                  F2;
  EFI_INPUT_KEY                  F7;
  EFI_INPUT_KEY                  F12;
  #ifdef XC_REQ
  EFI_INPUT_KEY                  CtrR;
  #endif

  EFI_BOOT_MANAGER_LOAD_OPTION   BootOption;
  UINTN                          OptionNumber;
  VOID                           *FileName;



  //Black.Blue = Black.Green = Black.Red = Black.Reserved = 0;
  //White.Blue = White.Green = White.Red = White.Reserved = 0xFF;
  //
  // Register ENTER as CONTINUE key
  //
  Enter.ScanCode    = SCAN_NULL;
  Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
  EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
  //
  // Map F2 to Boot Manager Menu
  //
  F2.ScanCode    = SCAN_F2;
  F2.UnicodeChar = CHAR_NULL;
  EfiBootManagerGetBootManagerMenu (&BootOption);
  EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL);
  //
  // 3. Boot Device List menu
  //
  F7.ScanCode     = SCAN_F7;
  F7.UnicodeChar  = CHAR_NULL;
  OptionNumber    = GetBootManagerMenuAppOption ();
  EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)OptionNumber, 0, &F7, NULL);

//add-klk-lyang-P000A-start//
  FileName = PcdGetPtr (PcdPxeBootFile);
  F12.ScanCode     = SCAN_F12;
  F12.UnicodeChar  = CHAR_NULL;
  OptionNumber    = GetHotkeyAppOption (FileName,L"UEFI PXE App");
  EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)OptionNumber, 0, &F12, NULL);

}

/**
  Returns the priority number.

  @param BootOption
**/
UINTN
BootOptionPriority (
  CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
  )
{
  //
  // Make sure Shell is first
  //
  if (StrCmp (BootOption->Description, L"UEFI Shell") == 0) {
    return 0;
  }
  return 100;
}

INTN
EFIAPI
CompareBootOption (
  CONST EFI_BOOT_MANAGER_LOAD_OPTION  *Left,
  CONST EFI_BOOT_MANAGER_LOAD_OPTION  *Right
  )
{
  return BootOptionPriority (Left) - BootOptionPriority (Right);
}
//start-klk-alt-P000A-add//
/**
  Return the index of the load option in the load option array.

  The function consider two load options are equal when the
  OptionType, Attributes, Description, FilePath and OptionalData are equal.

  @param Key    Pointer to the load option to be found.
  @param Array  Pointer to the array of load options to be found.
  @param Count  Number of entries in the Array.

  @retval -1          Key wasn't found in the Array.
  @retval 0 ~ Count-1 The index of the Key in the Array.
**/
INTN
PlatformFindLoadOption (
  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
  IN UINTN                              Count
)
{
  UINTN                             Index;

  for (Index = 0; Index < Count; Index++) {
    if ((Key->OptionType == Array[Index].OptionType) &&
        (Key->Attributes == Array[Index].Attributes) &&
        (StrCmp (Key->Description, Array[Index].Description) == 0) &&
        (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
        (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
        (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
      return (INTN) Index;
    }
  }

  return -1;
}

/**
  Register a boot option using a file GUID in the FV.

  @param FileGuid     The file GUID name in FV.
  @param Description  The boot option description.
  @param Attributes   The attributes used for the boot option loading.
**/
INTN
PlatformRegisterFvBootOption (
  EFI_GUID                         *FileGuid,
  CHAR16                           *Description,
  UINT32                           Attributes
  )
{
  EFI_STATUS                        Status;
  INTN                              OptionIndex;
  EFI_BOOT_MANAGER_LOAD_OPTION      NewOption;
  EFI_BOOT_MANAGER_LOAD_OPTION      *BootOptions;
  UINTN                             BootOptionCount;
  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;

  Status = gBS->HandleProtocol (
                  gImageHandle,
                  &gEfiLoadedImageProtocolGuid,
                  (VOID **) &LoadedImage
                  );
  ASSERT_EFI_ERROR (Status);

  EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
  DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
  ASSERT (DevicePath != NULL);
  DevicePath = AppendDevicePathNode (
                 DevicePath,
                 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
                 );
  ASSERT (DevicePath != NULL);

  Status = EfiBootManagerInitializeLoadOption (
             &NewOption,
             LoadOptionNumberUnassigned,
             LoadOptionTypeBoot,
             Attributes,
             Description,
             DevicePath,
             NULL,
             0
             );
  ASSERT_EFI_ERROR (Status);
  FreePool (DevicePath);

  BootOptions = EfiBootManagerGetLoadOptions (
                  &BootOptionCount, LoadOptionTypeBoot
                  );

  OptionIndex = EfiBootManagerFindLoadOption (
                  &NewOption, BootOptions, BootOptionCount
                  );

  if (OptionIndex == -1) {
    Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
    ASSERT_EFI_ERROR (Status);
    OptionIndex = NewOption.OptionNumber;
  } else {
  OptionIndex = BootOptions[OptionIndex].OptionNumber;
  }
  EfiBootManagerFreeLoadOption (&NewOption);
  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
  return OptionIndex;
}


//[jckuang-0016]
VOID
PlatformDeleteFvBootOption (
  EFI_GUID                         *FileGuid,
  CHAR16                           *Description,
  UINT32                           Attributes
)
{
  EFI_BOOT_MANAGER_LOAD_OPTION      *BootOptions;
  UINTN                             BootOptionCount;
  UINTN                             Index;

  BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);

  for (Index = 0; Index < BootOptionCount; Index++) {
    if ((LoadOptionTypeBoot == BootOptions[Index].OptionType) &&
        (StrCmp (Description, BootOptions[Index].Description) == 0)) {
      EfiBootManagerDeleteLoadOptionVariable (BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
      break;
    }
  }

  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
}
//[jckuang-0016]
//end-klk-alt-P000A-add//
VOID
EFIAPI
KlPlatformBdsConnectSequence (
  VOID
  )
{
  switch (GetBootModeHob ()) {
    case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
    case BOOT_WITH_MINIMAL_CONFIGURATION:
      PlatformBdsDiagnostics (IGNORE, TRUE);
      PlatformBdsConnectSequence ();
    break;

    case BOOT_IN_RECOVERY_MODE:
    break;
    case BOOT_ON_S4_RESUME:
    break;
    case BOOT_ON_FLASH_UPDATE:
      if (FeaturePcdGet(PcdSupportUpdateCapsuleReset)) {
        EfiBootManagerConnectAll ();
      }
    break;
    case BOOT_WITH_FULL_CONFIGURATION:
    case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
    case BOOT_WITH_DEFAULT_SETTINGS:
    default:
      PlatformBdsConnectSequence ();
    break;
  }
}

#define BOOT_OPTION_MAX_CHAR sizeof ("Boot####")
UINTN
BmStrSize (
  IN      CONST CHAR16              *String,
  IN      UINTN                     MaxStringLen
  )
{
  UINTN                             Length;

  ASSERT (String != NULL && MaxStringLen != 0);
  ASSERT (((UINTN) String & BIT0) == 0);

  for (Length = 0; *String != L'\0' && MaxStringLen != Length; String++, Length+=2);

  if (*String != L'\0' && MaxStringLen == Length) {
    return 0;
  }

  return Length + 2;
}

EFI_DEVICE_PATH_PROTOCOL *
GetDevicePathFromBootOption (
  IN  UINT16     OptionNum
  )
{
  CHAR16                     OptionName[BOOT_OPTION_MAX_CHAR];
  UINT8                      *BootOptionVar;
  UINTN                      VariableSize;
  UINT16                     FilePathSize;
  EFI_DEVICE_PATH_PROTOCOL   *DevicePath;
  UINTN                      DescriptionSize;

  //
  // Read the variable
  //
  UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionNum);
  GetVariable2 (OptionName, &gEfiGlobalVariableGuid, (VOID **) &BootOptionVar, &VariableSize);
  if (BootOptionVar == NULL) {
    return NULL;
  }

  if (VariableSize <= sizeof (UINT16) + sizeof (UINT32)) {
    return NULL;
  }

  //
  // Skip the option attribute
  //
  BootOptionVar += sizeof (UINT32);

  //
  // Get the option's device path size
  //
  FilePathSize = ReadUnaligned16 ((UINT16 *) BootOptionVar);
  BootOptionVar += sizeof (UINT16);

  //
  // Get the option's description string size
  //
  DescriptionSize = BmStrSize ((CHAR16 *) BootOptionVar, VariableSize - sizeof (UINT16) - sizeof (UINT32));
  BootOptionVar += DescriptionSize;

  //
  // Copy the contents of device path to allocated memory
  //
  DevicePath = AllocateCopyPool (FilePathSize, BootOptionVar);

  return DevicePath;
}

UINT32
GetAttributeFromBootOption (
  IN  UINT16     OptionNum
  )
{
  CHAR16                     OptionName[BOOT_OPTION_MAX_CHAR];
  UINT8                      *BootOptionVar;
  UINTN                      VariableSize;
  UINT32                     Attribute;

  //
  // Read the variable
  //
  UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionNum);
  GetVariable2 (OptionName, &gEfiGlobalVariableGuid, (VOID **) &BootOptionVar, &VariableSize);
  if (BootOptionVar == NULL) {
    return 0;
  }

  if (VariableSize <= sizeof (UINT16) + sizeof (UINT32)) {
    return 0;
  }

  Attribute = ReadUnaligned32 ((UINT32 *) BootOptionVar);

  return Attribute;
}


EFI_STATUS
UpdateFastbootDeviceVariable (
  VOID
  )
{
  UINT16                        *BootOrder;
  UINTN                         Size;
  EFI_DEVICE_PATH_PROTOCOL      *OptionDevicePath;
  EFI_DEVICE_PATH_PROTOCOL      *TmpOptionDevicePath;
  CHAR16                        *DevicePathStr;
  UINTN                         Index;
  UINT32                        Attribute;
  EFI_STATUS                    Status;
  UINTN                         TmpDevicePathLen;

  BootOrder = NULL;
  GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &Size);
  if (BootOrder == NULL) {
    DEBUG((DEBUG_INFO, "BootOrder NOT found for target device\n"));
    return EFI_NOT_FOUND;
  }

  for (Index = 0; Index < Size /sizeof(UINT16); Index++) {
    Attribute = GetAttributeFromBootOption (BootOrder[Index]);
    if((Attribute&LOAD_OPTION_HIDDEN) == LOAD_OPTION_HIDDEN) {
      continue;
    }
    if((Attribute&(LOAD_OPTION_CATEGORY_BOOT | LOAD_OPTION_ACTIVE)) == (LOAD_OPTION_CATEGORY_BOOT | LOAD_OPTION_ACTIVE)) {
      break;
    }
  }

  OptionDevicePath = GetDevicePathFromBootOption (BootOrder[Index]);
  if (OptionDevicePath == NULL) {
    DEBUG((DEBUG_INFO, "Boot order first option device path is NULL\n"));
    gBS->FreePool (BootOrder);
    return EFI_NOT_FOUND;
  }
  TmpOptionDevicePath = GetDevicePathFromBootOption (BootOrder[Index]);

  DevicePathStr = DevicePathToStr(OptionDevicePath);
  DEBUG((DEBUG_INFO, "BootOrder %x device path  %s\n",Index,DevicePathStr));

  DevicePathStr = DevicePathToStr(OptionDevicePath);
  DEBUG((DEBUG_INFO, "OptionDevicePath device path  %s\n",DevicePathStr));
  DEBUG((DEBUG_INFO, "UpdateTargetHddVariable\n"));

  TmpDevicePathLen = GetDevicePathSize (OptionDevicePath);

  #if 1
  Status = gRT->GetVariable (
                  L"TargetHddDevPath",
                  &gEfiGenericVariableGuid,
                  NULL,
                  &TmpDevicePathLen,
                  TmpOptionDevicePath
                  );
  if (EFI_ERROR (Status)) {
    gRT->SetVariable (
         L"TargetHddDevPath",
         &gEfiGenericVariableGuid,
         EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
         GetDevicePathSize (OptionDevicePath),
         OptionDevicePath
         );
  } else {
    if (CompareMem(OptionDevicePath, TmpOptionDevicePath, TmpDevicePathLen) != 0) {
      gRT->SetVariable (
         L"TargetHddDevPath",
         &gEfiGenericVariableGuid,
         EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
         GetDevicePathSize (OptionDevicePath),
         OptionDevicePath
         );
      DEBUG((DEBUG_INFO, "[ljw] path Not equal \n"));
    } else {
      DEBUG((DEBUG_INFO, "[ljw] path equal \n"));
    }
  }
  DevicePathStr = DevicePathToStr(OptionDevicePath);
  DEBUG((DEBUG_INFO, "Saved HDD boot device path  %s\n",DevicePathStr));
  #endif
  DEBUG((DEBUG_INFO, "UpdateTargetHddVariable5\n"));
  gBS->FreePool (OptionDevicePath);
  gBS->FreePool (BootOrder);

  return EFI_SUCCESS;
}
/**
  Do the platform specific action after the console is connected.

  Such as:
    Dynamically switch output mode;
    Signal console ready platform customized event;
    Run diagnostics like memory testing;
    Connect certain devices;
    Dispatch aditional option roms.
**/
VOID
EFIAPI
PlatformBootManagerAfterConsole (
  VOID
  )
{
//add-klk-lyang-P000A-start//
  ESRT_MANAGEMENT_PROTOCOL       *EsrtManagement;
  EFI_STATUS                     Status;
//add-klk-lyang-P000A-start//
  UINT32                         Attribute;
//add-klk-lyang-P000A-end//
 SYSTEM_SETUP_CONFIGURATION       *SetupVar = NULL;
 //[jckuang-0016]
  UINT8                           LocalShellBootSwitch;
  //[jckuang-0016]
  //UINT32                         Fastboot = 0;
  //[jckuang-0016]
  LocalShellBootSwitch = 1;

  //[jckuang-0016]
  Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
  if (EFI_ERROR(Status)) {
    EsrtManagement = NULL;
  }
//add-klk-lyang-P000A-end//
  //
  // Go the different platform policy with different boot mode
  // Notes: this part code can be change with the table policy
  //
  switch (GetBootModeHob ()) {

  case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
  case BOOT_WITH_MINIMAL_CONFIGURATION:
    //PlatformBdsDiagnostics (IGNORE, TRUE);

    //
    // Perform some platform specific connect sequence
    //
    //PlatformBdsConnectSequence ();
    break;

  case BOOT_IN_RECOVERY_MODE:
    PlatformBdsDiagnostics (EXTENSIVE, FALSE);
    break;
//add-klk-lyang-P000A-start//
  case BOOT_ON_S4_RESUME:
    EfiBootManagerRefreshAllBootOption ();
    break;
  case BOOT_ON_FLASH_UPDATE:
    if (FeaturePcdGet(PcdSupportUpdateCapsuleReset)) {
      //EfiBootManagerConnectAll ();
      EfiBootManagerRefreshAllBootOption ();

      //
      // Always sync ESRT Cache from FMP Instances after connect all and before capsule process
      //
      if (EsrtManagement != NULL) {
        EsrtManagement->SyncEsrtFmp();
      }

      DEBUG((DEBUG_INFO, "ProcessCapsules After ConnectAll ......\n"));
      Status = ProcessCapsules();
      DEBUG((DEBUG_INFO, "ProcessCapsules %r\n", Status));
    }
    break;
//add-klk-lyang-P000A-end//
  case BOOT_WITH_FULL_CONFIGURATION:
  case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
  case BOOT_WITH_DEFAULT_SETTINGS:
  default:
//remove-klk-lyang-P000A-start// logo display in consplitter
    //PlatformBdsDiagnostics (IGNORE, TRUE);
//remove-klk-lyang-P000A-end//
//remove-klk-lyang-P000A-start// move to before console
    //PlatformBdsRegisterStaticBootOptions ();
//remove-klk-lyang-P000A-end//
    //PlatformBdsConnectSequence ();
    EfiBootManagerRefreshAllBootOption ();
//add-klk-lyang-P000A-start//
    //if (!Fastboot) {
      UpdateFastbootDeviceVariable ();
    //}
    //
    // Sync ESRT Cache from FMP Instance on demand after Connect All
    //
    if (EsrtManagement != NULL) {
      EsrtManagement->SyncEsrtFmp();
    }
    break;
//add-klk-lyang-P000A-end//
//remove-klk-lyang-P000A-start//
    //EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, (SORT_COMPARE)CompareBootOption);
//remove-klk-lyang-P000A-end//
  }
//add-klk-lyang-P000A-start//
  //
  // Register UEFI Shell
  //
  //[jckuang-0016]
  #if 0
  Attribute = LOAD_OPTION_HIDDEN;
  if(FeaturePcdGet(PcdBootShellEnable)){
    Attribute = LOAD_OPTION_CATEGORY_BOOT | LOAD_OPTION_ACTIVE;
  }
  PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile), L"UEFI Shell", Attribute);
  #else
  if (LocalShellBootSwitch > 0) {
    Attribute = LOAD_OPTION_CATEGORY_BOOT | LOAD_OPTION_ACTIVE;
    PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile), L"UEFI Shell", Attribute);
  } else {
    PlatformDeleteFvBootOption(PcdGetPtr (PcdShellFile), L"UEFI Shell", LOAD_OPTION_CATEGORY_BOOT | LOAD_OPTION_ACTIVE);
  }
  #endif
  //[jckuang-0016]
//add-klk-lyang-P000A-start//
  PlatformRegisterFvBootOption (PcdGetPtr (PcdKlUpdateToolFile), L"Kunlun Update Tool", LOAD_OPTION_HIDDEN);
//add-klk-lyang-P000A-end//
  //KeyBoardStateControl();//[gliu-0051]
//add-klk-lyang-P000A-end//
//add-klk-lyang-P000A-start//

  DisplayPostMessage(SetupVar);

//add-klk-lyang-P000A-end//
  //[jckuang-0016]
  if(SetupVar != NULL){
    FreePool(SetupVar);
  }
  //[jckuang-0016]
}

/**
  This function is called each second during the boot manager waits the timeout.

  @param TimeoutRemain  The remaining timeout.
**/
VOID
EFIAPI
PlatformBootManagerWaitCallback (
  UINT16          TimeoutRemain
  )
{
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;
  UINT16                              Timeout;

  Timeout = PcdGet16 (PcdPlatformBootTimeOut);
  Timeout *= FRAME_PER_SECOND;
  Black.Raw = 0x00000000;
  White.Raw = 0x00FFFFFF;
  //add-klk-lyang-P000A-start//
  PlatformBdsShowProgress (
  White.Pixel,
  Black.Pixel,
  L"Start boot option",
  White.Pixel,
  ((Timeout - TimeoutRemain) * 1000 / Timeout),
  0
  );
  //add-klk-lyang-P000A-end//
//remove-klk-lyang-P000A-start//
  //BootLogoUpdateProgress (
  //White.Pixel,
  //Black.Pixel,
  //L"Start boot option",
  //White.Pixel,
  //(Timeout - TimeoutRemain) * 100 / Timeout,
  //0
  //);
//remove-klk-lyang-P000A-end//
}

/**
  The function is called when no boot option could be launched,
  including platform recovery options and options pointing to applications
  built into firmware volumes.

  If this function returns, BDS attempts to enter an infinite loop.
**/
VOID
EFIAPI
PlatformBootManagerUnableToBoot (
  VOID
  )
{
  CHAR8                       *CurrentLang;

  if(gST->ConOut == NULL){
    return;
  }
//add-klk-lyang-P000A-start//
  GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&CurrentLang, NULL);
//add-klk-lyang-P000A-start//
  gST->ConOut->EnableCursor (gST->ConOut, FALSE);
  gST->ConOut->ClearScreen (gST->ConOut);
//add-klk-lyang-P000A-end//
  if(CurrentLang != NULL && AsciiStrCmp ("zh-CN", CurrentLang) == 0){
    gST->ConOut->OutputString (gST->ConOut,L"无法启动系统！请按 ");  
    gST->ConOut->OutputString (gST->ConOut,L"CTRL+ALT+DELETE");
    gST->ConOut->OutputString (gST->ConOut,L"重启\r\n");
  }else{
    gST->ConOut->OutputString (gST->ConOut,L"Unable to boot! Please Insert Bootable Device to Boot!\r\n");
    gST->ConOut->OutputString (gST->ConOut,L"Please Press CTRL+ALT+DELETE to Reboot System!\r\n");
  }
//add-klk-lyang-P000A-end//
  return;
}

